package com.hwtx.form.persistence;

import com.baomidou.mybatisplus.core.batch.MybatisBatch;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.PageHelper;
import com.hwtx.form.domain.FormConstants;
import com.hwtx.form.domain.handle.datamodel.DataModel;
import com.hwtx.form.domain.handle.datamodel.DataModelDetail;
import com.hwtx.form.domain.handle.datamodel.DataModelRelate;
import com.hwtx.form.domain.repo.DataModelRepo;
import com.hwtx.form.domain.vo.DataModelDetailQuery;
import com.hwtx.form.domain.vo.DataModelQuery;
import com.hwtx.form.persistence.mapper.DataModelDetailMapper;
import com.hwtx.form.persistence.mapper.DataModelMapper;
import com.hwtx.form.persistence.mapper.DataModelRelateMapper;
import io.geekidea.boot.framework.page.Paging;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
@Slf4j
public class DataModelRepoImpl implements DataModelRepo {
    @Resource
    private DataModelMapper dataModelMapper;
    @Resource
    private DataModelDetailMapper dataModelDetailMapper;
    @Resource
    private DataModelRelateMapper dataModelRelateMapper;
    @Resource
    private SqlSessionFactory sqlSessionFactory;

    @Override
    public int saveDetail(DataModelDetail dataModelDetail) {
        return dataModelDetailMapper.insert(dataModelDetail);
    }

    @Override
    public void saveDetails(List<DataModelDetail> details) {
        MybatisBatch<DataModelDetail> mybatisBatch = new MybatisBatch<>(sqlSessionFactory, details);
        MybatisBatch.Method<DataModelDetail> method = new MybatisBatch.Method<>(DataModelDetailMapper.class);
        mybatisBatch.execute(method.insert());
    }

    @Override
    public int saveDataModel(DataModel dataModel) {
        return dataModelMapper.insert(dataModel);
    }

    @Override
    public int updateDataModel(DataModel dataModel) {
        return dataModelMapper.updateById(dataModel);
    }

    @Override
    public int updateDataModelDetailById(DataModelDetail dataModelDetail) {
        return dataModelDetailMapper.updateById(dataModelDetail);
    }

    @Override
    public List<DataModelDetail> getDetails(String modelName, FormConstants.Status status) {
        return getDetails(DataModelDetailQuery.builder().modelName(modelName).status(status).build());
    }

    @Override
    public List<DataModelDetail> getDetails(DataModelDetailQuery query) {
        LambdaQueryWrapper<DataModelDetail> queryWrapper = new LambdaQueryWrapper<>();
        if (CollectionUtils.isNotEmpty(query.getIds())) {
            queryWrapper.in(DataModelDetail::getId, query.getIds());
        }
        if (StringUtils.isNotBlank(query.getModelName())) {
            queryWrapper.eq(DataModelDetail::getModelName, query.getModelName());
        }
        if (query.getStatus() != null) {
            queryWrapper.eq(DataModelDetail::getStatus, query.getStatus().getCode());
        }
        if (CollectionUtils.isNotEmpty(query.getFields())) {
            queryWrapper.in(DataModelDetail::getName, query.getFields());
        }
        if (StringUtils.isNotBlank(query.getTableName())) {
            queryWrapper.eq(DataModelDetail::getTableName, query.getTableName());
        }
        if (query.getNum() != null) {
            queryWrapper.eq(DataModelDetail::getNum, query.getNum());
        }
        return dataModelDetailMapper.selectList(queryWrapper.orderByAsc(DataModelDetail::getNum));
    }

    @Override
    public Paging<DataModelDetail> pageDeDetails(int pageIndex, int pageSize, String modelName, FormConstants.Status status) {
        PageHelper.startPage(pageIndex, pageSize);
        List<DataModelDetail> details = dataModelDetailMapper.selectList(new LambdaQueryWrapper<DataModelDetail>().eq(DataModelDetail::getModelName, modelName).eq(DataModelDetail::getStatus, status.getCode()).orderByAsc(DataModelDetail::getNum));
        return new Paging<>(details);
    }

    @Override
    public Long countDetails(String modelName, FormConstants.Status status) {
        return dataModelDetailMapper.selectCount(new LambdaQueryWrapper<DataModelDetail>().eq(DataModelDetail::getModelName, modelName).eq(DataModelDetail::getStatus, status.getCode()));
    }

    @Override
    public boolean hasFields(String modelName, Object[] values) {
        Long count = dataModelDetailMapper.selectCount(new LambdaQueryWrapper<DataModelDetail>().eq(DataModelDetail::getModelName, modelName).in(DataModelDetail::getName, values));
        return count >= values.length;
    }

    @Override
    public boolean hasFields(String modelName, String table, Object[] columns) {
        Long count = dataModelDetailMapper.selectCount(new LambdaQueryWrapper<DataModelDetail>()
                .eq(DataModelDetail::getTableName, table)
                .eq(DataModelDetail::getModelName, modelName)
                .in(DataModelDetail::getName, columns));
        return count >= columns.length;
    }

    @Override
    public DataModelDetail getDetail(Long id) {
        return dataModelDetailMapper.selectById(id);
    }

    @Override
    public boolean deleteDetails(Long id) {
        return dataModelDetailMapper.deleteById(id) > 0;
    }

    @Override
    public void deleteDetails(String modelName, String table, FormConstants.Status status) {
        LambdaQueryWrapper<DataModelDetail> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DataModelDetail::getModelName, modelName);
        if (StringUtils.isNotBlank(table)) {
            queryWrapper.eq(DataModelDetail::getTableName, table);
        }
        if (status != null) {
            queryWrapper.eq(DataModelDetail::getStatus, status.getCode());
        }
        dataModelDetailMapper.delete(queryWrapper);
    }

    @Override
    public void deleteDataModel(Long id) {
        dataModelMapper.deleteById(id);
    }

    @Override
    public boolean deleteRelate(Long id) {
        return dataModelRelateMapper.deleteById(id) > 0;
    }

    @Override
    public void deleteRelate(String modelName) {
        dataModelRelateMapper.delete(new LambdaQueryWrapper<DataModelRelate>().eq(DataModelRelate::getModelName, modelName));
    }

    @Override
    public DataModel getDataModel(String modelName) {
        return dataModelMapper.selectOne(new LambdaQueryWrapper<DataModel>().eq(DataModel::getName, modelName));
    }

    @Override
    public DataModel getDataModel(Long id) {
        return dataModelMapper.selectById(id);
    }

    @Override
    public List<DataModel> getDataModels(DataModelQuery query) {
        LambdaQueryWrapper<DataModel> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(query.getModelName())) {
            lambdaQueryWrapper.like(DataModel::getName, query.getModelName());
        }
        if (StringUtils.isNotBlank(query.getDs())) {
            lambdaQueryWrapper.eq(DataModel::getDs, query.getDs());
        }
        return dataModelMapper.selectList(lambdaQueryWrapper.orderByDesc(DataModel::getUpdateTime));
    }

    @Override
    public List<DataModelRelate> getRelates(String modelName) {
        return dataModelRelateMapper.selectList(new LambdaQueryWrapper<DataModelRelate>().eq(DataModelRelate::getModelName, modelName));
    }

    @Override
    public void updateDetailModelName(String modelName, String oldModelName) {
        UpdateWrapper<DataModelDetail> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("model_name", oldModelName).set("model_name", modelName);
        dataModelDetailMapper.update(updateWrapper);
    }

    @Override
    public void updateDetails(List<DataModelDetail> details) {
        dataModelDetailMapper.updateById(details);
    }

    @Override
    public void updateRelateModelName(String modelName, String oldModelName) {
        UpdateWrapper<DataModelRelate> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("model_name", oldModelName).set("model_name", modelName);
        dataModelRelateMapper.update(updateWrapper);
    }

    @Override
    public int saveRelate(DataModelRelate dataModelRelate) {
        return dataModelRelateMapper.insert(dataModelRelate);
    }

    @Override
    public int updateRelate(DataModelRelate dataModelRelate) {
        return dataModelRelateMapper.updateById(dataModelRelate);
    }

    @Override
    public DataModelRelate getRelate(Long queryId) {
        return dataModelRelateMapper.selectById(queryId);
    }
}
